package com.acme.controller;

import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import com.acme.dao.UserDAO;
import com.acme.entity.User;
import com.acme.entity.security.AppSecurity;

@Controller
@Transactional
public class ResetUsernameController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

	@Autowired
	MailSender mailSender;

	@Autowired
	UserDAO userDAO;

	@RequestMapping(value = "resetusername", method = RequestMethod.GET)
	public String resetUsername() {
		return "ResetUsername";
	}

	@RequestMapping(value = "resetusername", method = RequestMethod.POST)
	public String sendUsernameResetEmail(@RequestParam (value = "emailField", required = true) String emailAddress) {
		User user = userDAO.getUserEmail(emailAddress);
		if(user == null) {
			return "redirect:/resetusername?foundUser=false";
		}
		SimpleMailMessage message = new SimpleMailMessage();
		message.setTo(emailAddress);
		message.setSubject("AcmeClaims Username Reset");
		String resetCode = AppSecurity.generateResetCode();
		String resetLink = ServletUriComponentsBuilder.fromCurrentContextPath().path("/resetuser?resetCode=" + resetCode + "&emailField=" + emailAddress).build().toUriString();
		String emailText = "If you have requested a username reset, follow this link to complete it: " + resetLink;
		message.setText(emailText);
		logger.info("Reset Code: " + resetCode);
		logger.info("Reset Link: " + resetLink);
		logger.info("Email Text: " + emailText);
		mailSender.send(message);
		String resetHash = "";
		try {
			resetHash = AppSecurity.createHash(resetCode);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		}
		user.setResetHash(resetHash);
		userDAO.updateUser(user);
		return "redirect:/resetusername?emailSent=true";
	}

	@RequestMapping(value = "resetuser", method = RequestMethod.GET)
	public ModelAndView newUsername(
			@RequestParam (value = "resetCode", required = true) String resetCode, 
			@RequestParam (value = "emailField", required = true) String emailField) {
		ModelAndView m = new ModelAndView();
		m.getModelMap().addAttribute("resetCode", resetCode);
		m.getModelMap().addAttribute("emailField", emailField);
		return m;
	}

	@RequestMapping(value = "resetuser", method = RequestMethod.POST)
	public String username(
			@RequestParam (value = "username", required = true) String username, 
			@RequestParam (value = "resetCode", required = true) String resetCode,
			@RequestParam (value = "emailField", required = true) String emailAddress) {
		User user = userDAO.getUserEmail(emailAddress);
		String resetHash = user.getResetHash();
		try {
			if(AppSecurity.validateHash(resetCode, resetHash) && userDAO.getUsername(username) == null) {
					logger.info("Username not found in database currently");
					user.setUsername(username);
					user.setResetHash(null);
					userDAO.updateUser(user);
					return "redirect:/resetusermessage?resetSuccess=true";	
			}
			else {
				logger.info("Username may have already exist in database currently");
				return "redirect:/resetusermessage?resetSuccess=false";
			}
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		}
		return "Login";
	}

	@RequestMapping(value = "resetusermessage", method = RequestMethod.GET)
	public String resetMessage() {return "ResetUserMessage";}
}
